#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
 
struct grid {
  int Np;                // number of gridpoints
  double a;              // left endpoint
  double b;              // right endpoint
  double dr;             // spatial step
  double* rgrid;         // pointer to array r
  double* ugrid;         // pointer to array u(r)
  double* vgrid;         // pointer to array v(r)

  double* dgrid;         // pointer to array ro(r)  
  double* der1;          // pointer to array of derivatives
  double* der2;          // pointer to array of sec. derivatives
  double* der1im;
  double* der2im;
  double* rhs;           // pointer to righthand side
  double* nonlocal;	 // pointer to nonlocal interaction term

  double* rhsim;
  double* tmp;           // extra array to organize RK 4
  double* tmpim;
  double* tmp2;          // one more for RK 4
  double* tmp2im;
  struct grid* lpointer; // pointer to grid on the left
  struct grid* rpointer; // pointer to grid on the right
};

struct SSdata {
  double Sstime;         // selfsimilar time
  double Phtime;         // physical time
  double L;              // self similar length
  double Lt;             // dL/dt
  double A;              // selfsimilar A;
  double phase;          // phase
  double phase_rr;	 // phase_rr
  double phi_rr;	 // |phi|_rr
  double phi;	 	 // |phi|	
};

struct INPdata {                // stores all input data
  FILE*   fh;
  char    runname[80];         //  name of run
  int      Ngrids;               //  number of starting grids   
  int      Npoints[128];  //  number of gridpoints on starting grids
  double   dr;                  // dr on smallest grid
  double   A;                   // Amplitude of IC
  double   lambda;              // CFL constant
  double   tmax;               //  Terminal time
  double   tinc;                //  time increment to write profile data to file
  int      Gaussian;            //  Type of initial condition
  double   sigma;               //  Width of gaussina type ICs
  int      Noutfile;             // how often to write SSdata
};

extern void initg(struct grid* in, int Np, double a, double dr);
extern void fillg(struct grid* in, double A, double sigma, int Gaussian);
extern void dump(FILE* fh, struct grid* in, double* time);
extern void read_p(FILE* fh, struct INPdata* input);
extern void sgaussIC(struct grid* in, int* Ngrids, double* A, double* sigma );
extern void write_out(FILE* fh, struct grid* in);
extern void read_in(FILE* fh, struct grid* in);
extern void init_p(int Ngrids, struct grid* in);
extern void glue(struct grid* in);
extern void d1r(struct grid* in);
extern void d2r(struct grid* in);
extern void rhs(double a, struct grid* in);
extern void density(struct grid* in);
extern void clearall(struct grid* in);
extern void writeall(FILE* fh, struct grid *m, struct SSdata *S, int *Ngrids);
extern void addgrid(struct grid* in, int *Ngrids);
extern void RK4(struct grid* in, double* dt, double a);
extern void startup(struct grid *in, struct INPdata *input, int *ac, char ***av);
extern double Nparticle(struct grid* in);
extern void non_local(double b, struct grid* in);
